package com.itkjb.leisurely.resource.sys.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.itkjb.leisurely.core.base.service.impl.TierBaseServiceImpl;
import com.itkjb.leisurely.core.exception.LeisurelyException;
import com.itkjb.leisurely.core.util.StatusUtils;
import com.itkjb.leisurely.core.util.TreeUtils;
import com.itkjb.leisurely.resource.common.DefaultButtonEnum;
import com.itkjb.leisurely.resource.common.SysConstants;
import com.itkjb.leisurely.resource.sys.mapper.SysMenuMapper;
import com.itkjb.leisurely.resource.sys.model.SysMenuModel;
import com.itkjb.leisurely.resource.sys.model.SysRoleModel;
import com.itkjb.leisurely.resource.sys.model.vo.SysMenuPermType;
import com.itkjb.leisurely.resource.sys.model.vo.SysMenuVO;
import com.itkjb.leisurely.resource.sys.service.ISysMenuService;
import com.itkjb.leisurely.resource.sys.service.ISysRoleService;
import com.itkjb.leisurely.resource.sys.service.ISysUserRoleService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * <p>
 * 系统菜单资源目录 服务实现类
 * </p>
 *
 * @author itkjb_gen
 * @since itkjb_gen
 */
@Service
public class SysMenuServiceImpl extends TierBaseServiceImpl<SysMenuMapper, SysMenuModel> implements ISysMenuService {

    @Autowired
    ISysRoleService roleService;
    /**
     * 保存按钮
     * @param model
     * @return
     */
    @Override
    public boolean saveButton(SysMenuModel model){
        SysMenuModel pmodel = this.getById(model.getParentId());
        if(pmodel == null){
            throw new LeisurelyException("未找到上级菜单");
        }
        if(StringUtils.isNotBlank(pmodel.getPermission())){
            model.setPermission(pmodel.getPermission()+":"+model.getCode());
        }
        return SqlHelper.retBool(this.baseMapper.insert(model));
    }
    /**
     * wrapper 组装器，构造条件查询
     * @author itkjb_gen
     * @date  itkjb_gen
     * @param wrapper
     * @param model 条件
     **/
    @Override
    protected void assembleWrapper(QueryWrapper<SysMenuModel> wrapper, SysMenuModel model) {
        wrapper.lambda().eq(model.getStatus()!=null, SysMenuModel::getStatus,model.getStatus() );
        wrapper.lambda().eq(model.getIsDel()!=null && model.getIsDel() == false, SysMenuModel::getIsDel,model.getIsDel() );
        if(model.getIds() !=null && model.getIds().size()>0){
            wrapper.lambda().in(SysMenuModel::getId,model.getIds());
        }
        if(model.getMenuType() != null){
            List<Integer> selectedStatus = StatusUtils.getSelectedStatus(model.getMenuType());
            wrapper.lambda().in(SysMenuModel::getMenuType, selectedStatus);
        }
        wrapper.lambda().eq(model.getParentId()!=null,SysMenuModel::getParentId,model.getParentId());
        wrapper.lambda().like(StringUtils.isNotBlank(model.getTitle()), SysMenuModel::getTitle , model.getTitle());


    }

    @Override
    protected void buildListSelectColumns(QueryWrapper<SysMenuModel> wrapper, SysMenuModel model) {
        wrapper.lambda().select(
                // id
                SysMenuModel::getId,
                // 菜单名字
                SysMenuModel::getTitle,
                // 菜单编码，解决前后端分离时为组成名称
                SysMenuModel::getCode,
                // 菜单url
                SysMenuModel::getPath,
                // 父级id
                SysMenuModel::getParentId,
                // 子节点数目
                SysMenuModel::getSubCount,
                // 图标样式
                SysMenuModel::getIcon,
                // 上传图标路径
                SysMenuModel::getImgPath,
                // 权限代码，尽可能保证唯一性
                SysMenuModel::getPermission,
                // 类型   1：目录   2：菜单   3：按钮
                SysMenuModel::getMenuType,
                // 菜单适配类型(1：PC端 2：移动端 )
                SysMenuModel::getMenuAdap,
                // 是否是外接系统,0:内网资源，1是外接资源，外链资源
                SysMenuModel::getIsOutside,
                // web端打开方式，1：当前页面框架中打开， 2：新页面打开
                SysMenuModel::getOpenType,
                // 系统编号
                SysMenuModel::getSysCode,
                // 是否是不可用的，0 不可用，1可用
                SysMenuModel::getStatus,
                // 系统id
                SysMenuModel::getTopId,
                // 排序
                SysMenuModel::getPaixu,
                // 部门id
                SysMenuModel::getDepId,

                SysMenuModel::getCreateTime
        );
    }

    /**
     * 组装菜单树
     * @param model
     * @return
     */
    @Override
    public List<SysMenuVO> tree(SysMenuModel model){
        QueryWrapper<SysMenuModel> wrapper  = new QueryWrapper<>();
        model.setIsDel(false);
        // 设置查找类型为 1 + 2 的类型，即 目录和按钮的类型
        if(model.getMenuType() ==null || model.getMenuType() == 0){
            model.setMenuType(SysConstants.MenuType.DIR.getKey()+SysConstants.MenuType.MENU.getKey());
        }
        buildListSelectColumns(wrapper,model);
        assembleWrapper(wrapper, model);
        List<SysMenuModel> sysMenuModels = this.baseMapper.selectList(wrapper);
        // 重新封装成树形菜单
        List<SysMenuVO> vos = new ArrayList<>();
        for(SysMenuModel sysMenuModel:sysMenuModels){
            SysMenuVO vo = new SysMenuVO();
            BeanUtils.copyProperties(sysMenuModel,vo);
            vos.add(vo);
        }
        TreeUtils<SysMenuVO> treeUtils = new TreeUtils<>();

        return treeUtils.tree(vos);
    }

    @Override
    public List<SysMenuVO> treeWithButton(SysMenuModel model){
        if(model == null){
            return null;
        }else{
            // 包括按钮 1+ 2+ 4
            model.setMenuType(SysConstants.MenuType.DIR.getKey()+SysConstants.MenuType.MENU.getKey()+SysConstants.MenuType.BUTTON.getKey());
            return tree(model);
        }
    }
    /**
     * 拼装菜单中的按钮信息
     * @param vos
     * @param bus
     */
    @Override
    public void treeWithButton(List<SysMenuVO> vos,List<SysMenuModel> bus){
        if(vos == null || vos.size()<=0){
            return ;
        }else if(bus == null || bus.size()<=0 ){
            return ;
        }
        for(SysMenuVO vo :vos){
            List<SysMenuModel> tembus = new ArrayList<>();
            for(SysMenuModel but :bus){
                if(vo.getId().equals(but.getParentId())){
                    SysMenuPermType type = new SysMenuPermType(but.getId(), but.getTitle(), but.getCode());
                    vo.getPermTypes().add(type);
                    tembus.add(but);
                }
            }
            bus.removeAll(tembus);
            if(vo.getChildren()!= null && vo.getChildren().size()>0){
                treeWithButton(vo.getChildren(), bus);
            }
        }
    }


    /**
     * 查询所有的button,可根据parentId,指定查询
     * @param model
     * @return
     */
    @Override
    public List<SysMenuModel> getButtons(SysMenuModel model){
        model.setMenuType(SysConstants.MenuType.BUTTON.getKey());
        QueryWrapper<SysMenuModel> wrapper  = new QueryWrapper<>();
        buildListSelectColumns(wrapper, model);
        assembleWrapper(wrapper, model);
        return  this.baseMapper.selectList(wrapper);
    }
    /**
     * 一键添加按钮菜单
     */
    @Override
    public boolean saveAutoAddButtonMenu(SysMenuModel model){
        if(model.getMenuType() == SysConstants.MenuType.DIR.getKey() ||
                model.getMenuType() == SysConstants.MenuType.MENU.getKey()){
            List<SysMenuModel> buttonList = new ArrayList<>();
            for(DefaultButtonEnum button: DefaultButtonEnum.values()){
                SysMenuModel menuModel = new SysMenuModel();
                menuModel.setParentId(model.getId());
                // 菜单类型 ，按钮
                menuModel.setMenuType(SysConstants.MenuType.BUTTON.getKey());
                menuModel.setTitle(button.getTitle());
                menuModel.setCode(button.getCode());
                if(StringUtils.isNotBlank(model.getPermission())){
                    menuModel.setPermission(model.getPermission()+":"+button.getCode());
                }
                buttonList.add(menuModel);
            }
            return this.saveBatch(buttonList);
        }
        return true;

    }

    /**
     * 逻辑删除
     * @param ids
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteByLogic(List<String> ids){
        // 菜单的ids, 这里区分开，是为了，统计重置菜单下级的数量
        List<String> menuIds = new ArrayList<>();
        // 按钮的ids
        List<String> buttonIds = new ArrayList<>();
        QueryWrapper<SysMenuModel> wrapper  = new QueryWrapper<>();
        wrapper.lambda().select(SysMenuModel::getId,SysMenuModel::getParentId,SysMenuModel::getMenuType).in(SysMenuModel::getId,ids);
        List<SysMenuModel> sysMenuModels = this.list(wrapper);
        // 区分出ids 中的菜单id和按钮id
        if(sysMenuModels!=null && sysMenuModels.size()>0){
            for(SysMenuModel menuModel:sysMenuModels){
                if(menuModel.getMenuType() == SysConstants.MenuType.DIR.getKey() || menuModel.getMenuType() == SysConstants.MenuType.MENU.getKey()){
                    menuIds.add(menuModel.getId());
                }else{
                    buttonIds.add(menuModel.getId());
                }
            }
        }
        // 只有菜单才有下级id
        getChildrenIds(menuIds,menuIds,buttonIds);
        if(menuIds !=null && menuIds.size()>0){
            this.removeByIds(menuIds);
        }
        if(buttonIds !=null && buttonIds.size()>0){
            this.baseMapper.deleteBatchIds(buttonIds);
        }

        return true;

    }

    @Override
    public List<String> getSubIds(String id) {
        List<String> parentIds = new ArrayList<>(1);
        List<String> res = new ArrayList<>();
        parentIds.add(id);
        this.getChildrenIds(parentIds,res,null);
        return res;
    }

    @Override
    public List<SysMenuModel> findMenuPermissionByRoleId(List<String> roleIds) {
        if(roleIds !=null && roleIds.size()>0){
            return this.baseMapper.findMenuPermissionByRoleId(roleIds);
        }
        return null;
    }

    @Override
    public List<SysMenuModel> findMenuPermissionByUserId(String userId) {
        List<SysRoleModel> temRoles = this.roleService.findRoleIdAndCodeByUserId(userId);
        List<SysMenuModel> res = null;
        if(temRoles !=null){
            List<String> roleIds = new ArrayList<>(temRoles.size());
            for (SysRoleModel temRole : temRoles) {
                roleIds.add(temRole.getId());
            }
            res = this.findMenuPermissionByRoleId(roleIds);
        }
        return res;
    }

    /**
     * 组装下级所有的ids
     * @param ids
     * @param menuIds 菜单的ids
     * @param buttonIds 按钮的ids
     */
    private void getChildrenIds(List<String> ids,List<String> menuIds, List<String> buttonIds){
        if(ids == null || ids.size()<=0){
            return ;
        }
        QueryWrapper<SysMenuModel> wrapper  = new QueryWrapper<>();
        wrapper.lambda().select(SysMenuModel::getId,SysMenuModel::getParentId,SysMenuModel::getMenuType).in(SysMenuModel::getParentId,ids);
        List<SysMenuModel> sysMenuModels = this.list(wrapper);
        if(sysMenuModels!=null && sysMenuModels.size()>0){

            List<String> temids = new ArrayList<>();
            for(SysMenuModel menuModel:sysMenuModels){
                if(menuModel.getMenuType() == SysConstants.MenuType.DIR.getKey() || menuModel.getMenuType() == SysConstants.MenuType.MENU.getKey()){
                    temids.add(menuModel.getId());
                }else{
                    if(buttonIds!=null){
                        buttonIds.add(menuModel.getId());
                    }
                }
            }
            menuIds.addAll(temids);
            getChildrenIds(temids, menuIds,buttonIds);
        }
    }


}
